From b3e03fa6f0e91ea088c47b7d4f0571dff847a3e1 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 4 Dec 2020 17:01:23 +0000 Subject: [PATCH] Add wrappers for setting the WidgetClass.activate_signal field Setting a field on a class structure is not always an easy task from languages other than C. While bindings can provide access to the class pointer, twiddling the fields in the class structure can be awkward. Additionally, signal ids are not always readily available. We can paper over the direct access to the class structure, as well as the "signal name to id" mapping with a simple couple of setter functions. --- docs/reference/gtk/gtk4-sections.txt | 2 + gtk/gtkwidget.c | 70 +++++++++++++++++++++++++++- gtk/gtkwidget.h | 7 +++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 77316a4fb6..66eae4da6a 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -4366,6 +4366,8 @@ gtk_widget_class_add_binding_signal gtk_widget_class_add_binding_action gtk_widget_class_set_layout_manager_type gtk_widget_class_get_layout_manager_type +gtk_widget_class_set_activate_signal +gtk_widget_class_set_activate_signal_from_name gtk_widget_activate gtk_widget_is_focus gtk_widget_grab_focus diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index ab9de00cd2..1ae404c425 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -4296,11 +4296,22 @@ gtk_widget_mnemonic_activate (GtkWidget *widget, return handled; } +static gboolean +gtk_widget_can_activate (GtkWidget *self) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (self); + + if (widget_class->activate_signal != 0) + return TRUE; + + return FALSE; +} + static gboolean gtk_widget_real_mnemonic_activate (GtkWidget *widget, gboolean group_cycling) { - if (!group_cycling && GTK_WIDGET_GET_CLASS (widget)->activate_signal) + if (!group_cycling && gtk_widget_can_activate (widget)) gtk_widget_activate (widget); else if (gtk_widget_get_can_focus (widget)) return gtk_widget_grab_focus (widget); @@ -4562,6 +4573,61 @@ gtk_widget_event (GtkWidget *widget, return return_val; } +/** + * gtk_widget_class_set_activate_signal: + * @widget_class: a #GtkWidgetClass + * @signal_id: the id for the activate signal + * + * Sets the #GtkWidgetClass.activate_signal field with the + * given @signal_id; the signal will be emitted when calling + * gtk_widget_activate(). + * + * The @signal_id must have been registered with g_signal_new() + * or g_signal_newv() before calling this function. + */ +void +gtk_widget_class_set_activate_signal (GtkWidgetClass *widget_class, + guint signal_id) +{ + g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class)); + g_return_if_fail (signal_id != 0); + + widget_class->activate_signal = signal_id; +} + +/** + * gtk_widget_class_set_activate_signal_from_name: + * @widget_class: a #GtkWidgetClass + * @signal_name: the name of the activate signal of @widget_type + * + * Sets the #GtkWidgetClass.activate_signal field with the signal id for + * the given @signal_name; the signal will be emitted when calling + * gtk_widget_activate(). + * + * The @signal_name of @widget_type must have been registered with + * g_signal_new() or g_signal_newv() before calling this function. + */ +void +gtk_widget_class_set_activate_signal_from_name (GtkWidgetClass *widget_class, + const char *signal_name) +{ + guint signal_id; + + g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class)); + g_return_if_fail (signal_name != NULL); + + signal_id = g_signal_lookup (signal_name, G_TYPE_FROM_CLASS (widget_class)); + if (signal_id == 0) + { + g_critical ("Widget type “%s” does not have a “%s” signal", + G_OBJECT_CLASS_NAME (widget_class), + signal_name); + return; + } + + widget_class->activate_signal = signal_id; +} + /** * gtk_widget_activate: * @widget: a #GtkWidget that’s activatable @@ -4578,7 +4644,7 @@ gtk_widget_activate (GtkWidget *widget) { g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); - if (GTK_WIDGET_GET_CLASS (widget)->activate_signal) + if (gtk_widget_can_activate (widget)) { /* FIXME: we should eventually check the signals signature here */ g_signal_emit (widget, GTK_WIDGET_GET_CLASS (widget)->activate_signal, 0); diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index 61379b558e..8aa2403ac9 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -364,6 +364,13 @@ GDK_AVAILABLE_IN_ALL void gtk_widget_class_add_shortcut (GtkWidgetClass *widget_class, GtkShortcut *shortcut); +GDK_AVAILABLE_IN_ALL +void gtk_widget_class_set_activate_signal (GtkWidgetClass *widget_class, + guint signal_id); +GDK_AVAILABLE_IN_ALL +void gtk_widget_class_set_activate_signal_from_name (GtkWidgetClass *widget_class, + const char *signal_name); + GDK_AVAILABLE_IN_ALL gboolean gtk_widget_mnemonic_activate (GtkWidget *widget, gboolean group_cycling); -- 2.30.2